package com.example.socket.server.aio;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;

public class ServerCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {

    /**
     * 监听方法，监听客户端
     * @param result
     * @param attachment
     */
    @Override
    public void completed(AsynchronousSocketChannel result, Server attachment) {
        /**
         * 当有下一个客户端接入进来时，直接调用 Server的accept 方法，这样反复执行下去，保证多个客户端都可以阻塞
         */
        attachment.serverSocketChannel.accept(attachment, this);
        read(result);

    }

    @Override
    public void failed(Throwable exc, Server attachment) {

    }

    private void read(AsynchronousSocketChannel asc){
        //读取数据缓冲区
        ByteBuffer buf = ByteBuffer.allocate(1024);
        //异步读取数据
        asc.read(buf, buf, new CompletionHandler<Integer, ByteBuffer>() {

            /**
             * 读取数据
             * @param result 字节长度
             * @param attachment 字符缓冲区
             */
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                //进行读取数据后，重置标识位
                attachment.flip();
                //获得读取数据的长度
                System.out.println("服务端读取客户端数据长度："+result);
                //获得读取的数据
                String data = null;
                try {
                    data = new String(attachment.array(),0,result,"GBK").trim();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                System.out.println("服务端读取客户端数据："+data);
                String response = "服务器响应，接收到客户端发送的数据："+data;
                write(asc, response);
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                exc.printStackTrace();
            }
        });
    }

    /**
     * 处理返回客户端数据
     *
     * @param asc
     * @param response
     */
    private void write(AsynchronousSocketChannel asc, String response) {
        try {
            //写入数据缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //写入缓冲区
            buf.put(response.getBytes());
            //进行读取数据后，重置标识位 复位
            buf.flip();
            //写出数据 异步写数据
            asc.write(buf).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}
